﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace FRL.DebtChased.Silverlight.Library
{

	/// <summary>
	/// Declaration of AutoCompleteDropCtrl class
	/// Control for dropping a list of predefined options for textbox entry
	/// plus buttons for adding and removing from list of predefined options
	/// </summary>
	public partial class AutoCompleteDropCtrl : UserControl
	{

		/////////////////////////////////////////////////////////////
		// Delegates and events

		public event RoutedEventHandler TextChanged;

		/////////////////////////////////////////////////////////////
		// Attributes

		public Style UnderlyingAutoCompleteBoxStyle
		{
			get { return autoCompleteBox.Style; }
			set { autoCompleteBox.Style = value; }
		}

		public string Text
		{
			get { return autoCompleteBox.Text ?? string.Empty; }
			set { autoCompleteBox.Text = value; }
		}

		public int MinEntryChars
		{
			get { return autoCompleteBox.MinChars; }
			set { autoCompleteBox.MinChars = value; }
		}

		public bool StandardMode
		{
			get { return autoCompleteBox.StandardMode; }
			set { autoCompleteBox.StandardMode = value; }
		}

		public bool IsContentGood
		{
			get { return autoCompleteBox.IsContentGood; }
		}

		public bool EntryMustBeInList
		{
			get { return autoCompleteBox.EntryMustBeInList; }
			set { autoCompleteBox.EntryMustBeInList = value; }
		}

		public int MinCompleteChars
		{
			get { return autoCompleteBox.MinChars; }
			set { autoCompleteBox.MinChars = value; }
		}

		private ObservableCollection<string> m_stringList;
		public ObservableCollection<string> StringList
		{
			set 
			{ 
				
				// Update the member
				m_stringList = value; 

				// Bind to list
				autoCompleteBox.ItemsSource = m_stringList;

				// Setup controls
				_setupControls();

			}
		}

		// The reusable string category
		private string m_strCategory;
		public string Category
		{
			get { return m_strCategory; }
			set { m_strCategory = value; }
		}

		/////////////////////////////////////////////////////////////
		// Construction

		public AutoCompleteDropCtrl()
		{

			// Initialize resources
			InitializeComponent();

			// Exit function in design mode
			if (CachedDataBase.SingletonBase == null)
				return;

			// Add handler for text change
			autoCompleteBox.TextChanged += new RoutedEventHandler(AutoCompleteBox_TextChanged);

			// Apply for event when reuseable string changes
			if(CachedDataBase.SingletonBase != null)
				CachedDataBase.SingletonBase.ReusableStringChange += new EventHandler<ReusableStringChangeEventArg>(Singleton_ReusableStringChange);

			// Setup controls
			_setupControls();

		}

		/////////////////////////////////////////////////////////////
		// Event handlers

		private void butDrop_Click(object sender, RoutedEventArgs e)
		{

			// If there are some entries to drop...
			if (autoCompleteBox.ItemsSource != null)
			{

				// Open the drop-down if not already open
				if (!autoCompleteBox.IsDropDownOpen)
					autoCompleteBox.IsDropDownOpen = true;

			}

		}

		private void butAdd_Click(object sender, RoutedEventArgs e)
		{

			// Call main-page function
			CachedDataBase.SingletonBase.AddReusableString( m_strCategory, autoCompleteBox.Text, true );

			// Setup controls
			_setupControls();

		}

		private void butRemove_Click(object sender, RoutedEventArgs e)
		{

			// Call main-page function
			CachedDataBase.SingletonBase.AddReusableString(m_strCategory, autoCompleteBox.Text, false);

			// Setup controls
			_setupControls();

		}

		void AutoCompleteBox_TextChanged(object sender, RoutedEventArgs e)
		{

			// Setup controls
			_setupControls();

			// route the event out
			if (TextChanged != null)
				TextChanged(sender, e);
			
		}

		private void UserControl_KeyDown(object sender, KeyEventArgs e)
		{

			// If escape, and drop-down is open and this control has focus...
			if (
				(!string.IsNullOrEmpty(m_strCategory))
				&&
				(e.Key == Key.Escape)
				&&
				(autoCompleteBox.IsDropDownOpen)
			)
			{

				// Close the drop-down and cancel the key event
				autoCompleteBox.IsDropDownOpen = false;
				e.Handled = true;

			}

		}

		private void autoCompleteBox_DropDownOpening(object sender, RoutedPropertyChangingEventArgs<bool> e)
		{

			// Apply border
			autoCompleteBox.BorderThickness = new Thickness(2);

		}

		private void autoCompleteBox_DropDownClosing(object sender, RoutedPropertyChangingEventArgs<bool> e)
		{

			// Apply border
			autoCompleteBox.BorderThickness = new Thickness(0);

		}

		void Singleton_ReusableStringChange(object sender, ReusableStringChangeEventArg e)
		{

			// If the category matches...
			if (e.Category == m_strCategory)
			{

				// Setup controls
				_setupControls();

			}
			
		}

		/////////////////////////////////////////////////////////////
		// Operations

		public void SetFirstItem()
		{

			// Get the list of strings
			if( (m_stringList!=null) && (m_stringList.Count>0) )
				this.Text = m_stringList[0];

			// Setup controls
			_setupControls();

		}

		private void _setupControls()
		{

			// enable/disable controls
			butDrop.IsEnabled = (m_stringList!=null);

			// show/hide controls
			if (
				(!string.IsNullOrEmpty(m_strCategory)) 
				&&
				(m_stringList != null) 
				&& 
				(!string.IsNullOrEmpty(autoCompleteBox.Text)) 
			)
			{

				// Find string in list
				bool bFound = (m_stringList.Count(s => (string.Compare(s, autoCompleteBox.Text, StringComparison.CurrentCultureIgnoreCase) == 0)) > 0);

				// Is string already in the list...
				if (bFound)
				{
					butAdd.Visibility = System.Windows.Visibility.Collapsed;
					butRemove.Visibility = System.Windows.Visibility.Visible;
				}
				else
				{
					butAdd.Visibility = System.Windows.Visibility.Visible;
					butRemove.Visibility = System.Windows.Visibility.Collapsed;
				}

			}
			else
			{
				butAdd.Visibility = System.Windows.Visibility.Collapsed;
				butRemove.Visibility = System.Windows.Visibility.Collapsed;
			}

		}

	}

	/// <summary>
	/// Declaration of ExAutoCompleteBox class
	/// The underlying AutoCompleteBox-based class uses in the AutoCompleteDropCtrl
	/// </summary>
	public class ExAutoCompleteBox : AutoCompleteBox
	{

		/////////////////////////////////////////////////////////////
		// Attributes

		private int m_iMinChars = 0;
		public int MinChars
		{
			get { return m_iMinChars; }
			set { m_iMinChars = value; }
		}

		private bool m_bStandardMode = false;
		public bool StandardMode
		{
			get { return m_bStandardMode; }
			set { m_bStandardMode = value; }
		}

		private bool m_bEntryMustBeInList = false;
		public bool EntryMustBeInList
		{
			get { return m_bEntryMustBeInList; }
			set { m_bEntryMustBeInList = value; }
		}

		public bool IsContentGood
		{
			get 
			{

				// Check text length
				if (
					(m_iMinChars != 0) 
					&&
					(
						(base.Text == null)
						||
						(base.Text.Length < m_iMinChars)
					)
				)
					return false;

				// Check against list
				if (
					(m_bEntryMustBeInList)
					&&
					(base.ItemsSource != null)
				)
				{
					ObservableCollection<string> list = base.ItemsSource as ObservableCollection<string>;
					if (!list.Contains(base.Text))
						return false;
				}

				// Return success
				return true;

			}

		}

		private Brush m_brushOriginalBackground;

		private static Brush m_brushErrorBackground;

		/////////////////////////////////////////////////////////////
		// Construction

		static ExAutoCompleteBox()
		{

			// Initialize member variables
			m_brushErrorBackground = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF, 0xE0, 0xE0));

		}

		public ExAutoCompleteBox()
		{

			// Set a custom filter
			this.TextFilter = _customFilter;
			this.MinimumPrefixLength = 0;

			// Set up event handlers
			base.TextChanged += new RoutedEventHandler(ExAutoCompleteBox_TextChanged);
			base.Loaded += new RoutedEventHandler(ExAutoCompleteBox_Loaded);

		}

		/////////////////////////////////////////////////////////////
		// Event handlers

		void ExAutoCompleteBox_Loaded(object sender, RoutedEventArgs e)
		{

			// Setup colours
			ExAutoCompleteBox_TextChanged(null, null);

		}

		void ExAutoCompleteBox_TextChanged(object sender, RoutedEventArgs e)
		{

			// If showing error...
			if (!this.IsContentGood)
			{
				if (base.Background != m_brushErrorBackground)
				{
					m_brushOriginalBackground = base.Background;
					base.Background = m_brushErrorBackground;
				}
			}
			else
			{
				if(
					(m_brushOriginalBackground != null)
					&&
					(base.Background != m_brushOriginalBackground)
				)
					base.Background = m_brushOriginalBackground;
			}

		}

		protected override void OnPopulated(PopulatedEventArgs e)
		{

			// Call base-class function
			base.OnPopulated(e);

		}

		/////////////////////////////////////////////////////////////
		// Operations

		private bool _customFilter(string search, string value)
		{

			// Shortcuts
			if (!m_bStandardMode)
				return true;

			// Check for string in string
			return value.StartsWith(search, StringComparison.CurrentCultureIgnoreCase);

		}

	}

}
